/*
 *
 * Copyright 2021-2025 Software Radio Systems Limited
 *
 * This file is part of srsRAN.
 *
 * srsRAN is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * srsRAN is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * A copy of the GNU Affero General Public License can be found in
 * the LICENSE file in the top-level directory of this distribution
 * and at http://www.gnu.org/licenses/.
 *
 */

#pragma once

#include <condition_variable>
#include <mutex>

namespace srsran {

/// \brief Baton synchronization primitive.
///
/// It is used to synchronize two threads, where one waits for the other to finish.
class baton
{
public:
  void post()
  {
    std::lock_guard<std::mutex> lock(mutex);
    is_set = true;
    cvar.notify_one();
  }

  void wait()
  {
    std::unique_lock<std::mutex> lock(mutex);
    cvar.wait(lock, [this] { return is_set; });
  }

private:
  std::mutex              mutex;
  std::condition_variable cvar;
  bool                    is_set = false;
};

/// RAII helper for baton synchronization primitive.
class scoped_baton_sender
{
  struct deleter {
    void operator()(baton* p)
    {
      if (p != nullptr) {
        p->post();
      }
    }
  };

public:
  scoped_baton_sender(baton& parent_) : parent(&parent_) {}
  void post() { parent = nullptr; }

private:
  // Use of unique_ptr for RAII
  std::unique_ptr<baton, deleter> parent;
};

} // namespace srsran
